package com.gmrz.uap.serviceplugin;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.gmrz.uap.authenticators.AuthenticatorsService;
import com.gmrz.uap.authmetadata.AuthMetadataService;
import com.gmrz.uap.cache.AmmsCacheUtil;
import com.gmrz.uap.cache.CacheStoreService;
import com.gmrz.uap.cfg.SystemConst;
import com.gmrz.uap.common.ConditionConst;
import com.gmrz.uap.common.ControllerSupport;
import com.gmrz.uap.common.DbConst;
import com.gmrz.uap.common.UAPSSOHelper;
import com.gmrz.uap.datastatistics.DataStatisticsService;
import com.gmrz.uap.model.*;
import com.gmrz.uap.operlog.OperLogService;
import com.gmrz.uap.resource.ResourceInterceptor;
import com.gmrz.uap.util.ExcelUtil;
import com.gmrz.uap.util.Identities;
import com.gmrz.uap.util.JSONUtils;
import com.gmrz.uap.util.Strings;
import com.jfinal.aop.Before;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.render.JsonRender;
import com.jfinal.upload.ExceededSizeException;
import com.jfinal.upload.UploadFile;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import redis.clients.jedis.exceptions.JedisConnectionException;

import java.io.*;
import java.util.*;

public class ServicePluginController extends ControllerSupport {

    private static final Logger LOG = LogManager.getLogger(ServicePluginController.class);

    /**
     * 插件参数管理主页面
     */
    @Before(ResourceInterceptor.class)
    public void index() {
    }

    /**
     * 根据前台发过来的参数进行查询，可以进行分页，排序
     */
    public void list() {

        int page = getParaToInt(SystemConst.DATATABLE_PAGINATE_OFFSET, SystemConst.DATATABLE_PAGINATE_OFFSET_DEFAULT);
        int rows = getParaToInt(SystemConst.DATATABLE_PAGINATE_LIMIT, SystemConst.DATATABLE_PAGINATE_LIMIT_DEFAULT);

        String sort = getPara(SystemConst.DATATABLE_PAGINATE_SORT, DbConst.TABLE_DICT_COLUMN_ORDER_NUMBER);
        String order = getPara(SystemConst.DATATABLE_PAGINATE_ORDER, SystemConst.DATATABLE_PAGINATE_ORDER_DEFAULT);

        PluginArgument pluginArgument = getModel(PluginArgument.class);
        if(pluginArgument.get("sp_id").equals("f5d5f8616ba040e0a76ca7d6058a4441")){
            String tenantId = getCookie(SystemConst.COOKIE_TENANT_ID);
            pluginArgument.set("tenant_id",tenantId);
        }
        LOG.info(pluginArgument.toString());

        Page<PluginArgument> descPage = ServicePluginService.me.findListForPaginate(pluginArgument, page, rows, sort, order, getCookie(SystemConst.COOKIE_TENANT_ID));

        result.put(SystemConst.DATATABLE_PAGINATE_TOTAL, descPage.getTotalRow());
        result.put(SystemConst.DATATABLE_PAGINATE_ROWS, descPage.getList());

        render(responseJsonRender(result));
    }


    /**
     * 增加页面跳转
     */

    public void add() {
        PluginArgument pluginArgument = getModel(PluginArgument.class);
        setAttr("pluginArgument", pluginArgument);
        render("form" + SystemConst.VIEW_EXTENDSION);
    }

    /**
     * 保存数据信息
     */
    public void save() {

        PluginArgument pluginArgument = getModel(PluginArgument.class);

        if (null == pluginArgument) {
            message = getRes().get("system.validator.paramnull");
            result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
            render(responseJsonRender(result));
            return;
        }
        if(pluginArgument.get("sp_id").equals("f5d5f8616ba040e0a76ca7d6058a4441")){
            String tenantId = getCookie(SystemConst.COOKIE_TENANT_ID);
            pluginArgument.set("tenant_id",tenantId);
        }
        flag = ServicePluginService.me.save(pluginArgument);

        if (flag) {

            try {
                message = getRes().get("system.validator.add.success");
                message = ServicePluginService.me.modifyCache(pluginArgument.getStr(DbConst.TABLE_PLUGIN_ARGUMENT_COLUMN_SP_ID),message);
            } catch (JedisConnectionException e) {
                flag = true;
                message += getRes().get("redis.connection.failed");
                LOG.error(message, e);
            }
        } else {
            message = getRes().get("system.validator.add.error");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("serviceplugin.form.add"), pluginArgument.getStr(DbConst.TABLE_PLUGIN_ARGUMENT_COLUMN_CONFIG_CNAME), flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

    /**
     * 编辑页面跳转
     */
    public void edit() {
        PluginArgument pluginArgument = PluginArgument.dao.findById(getPara());
        setAttr("pluginArgument", pluginArgument);
        render("form" + SystemConst.VIEW_EXTENDSION);
    }

    /**
     * 修改数据信息
     */
    public void update() {
        PluginArgument pluginArgument = getModel(PluginArgument.class);

        if (null == pluginArgument) {
            message = getRes().get("system.validator.paramnull");
            result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
            render(responseJsonRender(result));
            return;
        }
        String spID = pluginArgument.get("sp_id");
        if(spID.equals("f5d5f8616ba040e0a76ca7d6058a4441")){
            String tenantId = getCookie(SystemConst.COOKIE_TENANT_ID);
            pluginArgument.set("tenant_id",tenantId);
        }
        flag = ServicePluginService.me.update(pluginArgument);

        if (flag) {

            try {
                message = getRes().get("system.validator.edit.success");
                message =  ServicePluginService.me.modifyCache(pluginArgument.getStr(DbConst.TABLE_PLUGIN_ARGUMENT_COLUMN_SP_ID),message);
            } catch (JedisConnectionException e) {
                flag = true;
                message += getRes().get("redis.connection.failed");
                LOG.error(message, e);
            }
        } else {
            message = getRes().get("system.validator.edit.error");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("serviceplugin.form.edit"), /*pluginArgument.getVisitAddress()*/"", flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

    /**
     * 根据ID删除数据信息，可以同时删除多个，数据使用逗号(,)隔开
     */
    public void remove() {

        String ids = getPara("ids");
        String spId = getPara("spId");

        if (StrKit.isBlank(ids)) {
            message = getRes().get("system.validator.paramnull");
            render(responseJsonRender(result));
        }

        flag = ServicePluginService.me.remove(ids);

        if (flag) {

            try {
                message = getRes().get("system.validator.remove.success");
                message = ServicePluginService.me.modifyCache(spId,message);
            } catch (JedisConnectionException e) {
                flag = true;
                message += getRes().get("redis.connection.failed");
                LOG.error(message, e);
            }
        } else {
            message = getRes().get("system.validator.remove.error");
        }

        //增加系统操作日志
        OperLogService.me.addOperLog(getRes().get("serviceplugin.form.remove"), ids, flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }


    /**
     * 判断访问地址是否存在
     */
    public void exist() {
        flag = ServicePluginService.me.exist(getPara("pluginArgument.config_name"));
        render(responseJsonRender(flag));
    }

    @Before(ResourceInterceptor.class)
    public void servicePluginFace() {
        String spId = "362a34d1b289433085dacda9f9bd49eb";
        ServicePlugin servicePlugin = ServicePlugin.dao.findById(spId);
        setAttr("servicePlugin", servicePlugin);
        setAttr("pluginType", "10");
        render("index" + SystemConst.VIEW_EXTENDSION);
    }

    @Before(ResourceInterceptor.class)
    public void servicePluginVoice() {
        String spId = "f9fec3a20b72458abf7894a5a35fb002";
        ServicePlugin servicePlugin = ServicePlugin.dao.findById(spId);
        setAttr("servicePlugin", servicePlugin);
        setAttr("pluginType", "11");
        render("index" + SystemConst.VIEW_EXTENDSION);
    }

    @Before(ResourceInterceptor.class)
    public void servicePluginAutonym() {
        String spId = "e774166cdc0949699ba3001f88af177e";
        ServicePlugin servicePlugin = ServicePlugin.dao.findById(spId);
        setAttr("servicePlugin", servicePlugin);
        setAttr("pluginType", "12");
        render("index" + SystemConst.VIEW_EXTENDSION);
    }

    @Before(ResourceInterceptor.class)
    public void servicePluginFaceAndRealName() {
        String spId = "243b7343d6fd4d51b11f14c290c322f0";
        ServicePlugin servicePlugin = ServicePlugin.dao.findById(spId);
        setAttr("servicePlugin", servicePlugin);
        setAttr("pluginType", "13");
        render("index" + SystemConst.VIEW_EXTENDSION);
    }

    @Before(ResourceInterceptor.class)
    public void servicePluginDigitalCertificate() {
        String spId = "f5d5f8616ba040e0a76ca7d6058a4441";
        ServicePlugin servicePlugin = ServicePlugin.dao.findById(spId);
        setAttr("servicePlugin", servicePlugin);
        setAttr("pluginType", "14");
        render("index" + SystemConst.VIEW_EXTENDSION);
    }


    /**
     * 对授权证书的编辑
     */
    public void authorization() {
        Dict dict = Dict.dao.findById(Dict.DICT_ID_CERT);
        setAttr("dict", dict);
        render("authorization" + SystemConst.VIEW_EXTENDSION);
    }


    public void authorizationSave() {
        Dict dict = getModel(Dict.class);
        flag = dict.update();
        if (flag) {
            message = "证书授权成功！";
            message = AmmsCacheUtil.deleteIfSuccess(AmmsCacheUtil.CACHE_CERT_AHTH_INFO, message);
        } else {
            message = "证书授权失败，请稍后重试！";
        }

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        render(responseJsonRender(result));
    }

    /**
     * 查看证书使用情况
     */
    public void certStatistics() {

        Dict dict = Dict.dao.findById(Dict.DICT_ID_CERT);
        //String[] certArr = ( dict.getDictText()!=null ? dict.getDictText().split("\\*") : null );
        //setAttr("certAuthNo", (certArr != null ? certArr[0] : ""));

        byte[] base64 = Base64.decodeBase64(dict.getDictText());
        String certJson = new String(base64);

        JSONObject jsonObject = JSONObject.parseObject(certJson);
        JSONObject jsonInfo = (JSONObject) jsonObject.get("info");

        List<Record> list = new ArrayList<>();
        Record r ;
        Set<Map.Entry<String, Object>> infoSet =  jsonInfo.entrySet();
        Iterator i = infoSet.iterator();

        while(i.hasNext()){
            Map.Entry<String, Object> e = (Map.Entry<String, Object>) i.next();
            int certMaxNo = 0;
            String certAuthNo = null;
            if ("k".equals(e.getKey())){
                certAuthNo = SystemConst.CERT_SECURE_LEVEL_TEE;
                certMaxNo = Certificate.dao.getMaxCertNo(certAuthNo);
            }
            if ("s".equals(e.getKey())){
                certAuthNo = SystemConst.CERT_SECURE_LEVEL_SE;
                certMaxNo = Certificate.dao.getMaxCertNo(certAuthNo);
            }
            if ("t".equals(e.getKey())){
                certAuthNo = SystemConst.CERT_SECURE_LEVEL_TEEANDTUI;
                certMaxNo = Certificate.dao.getMaxCertNo(certAuthNo);
            }
            if(!"c".equals(e.getKey()) && !"0".equals(e.getValue().toString())){
                r = new Record();
                r.set("certAuthNo", certAuthNo);
                r.set("certAuthNoNum", e.getValue());
                r.set("certMaxNo", certMaxNo);
                list.add(r);
            }
        }
        // 每种安全等级的证书使用数量
        setAttr("certificateAuthList", list);

        // 查询每个认证器证书使用数量
        List<Record> certificateList = Certificate.dao.getCertCountByAAID();
        setAttr("certificateList", certificateList);

        render("certStatistics" + SystemConst.VIEW_EXTENDSION);
    }




    /**
     * 跳转证书使用明细页面
     */
    public void certUseDetail() {
        User cacheUser = UAPSSOHelper.getUserByUapSessionId(getRequest());
        // 判断当前用户是否有权限
        boolean permissions = isTherePermissions();
        if (!permissions){
            // 机构用户, 不让导出明细
            setAttr("permissions", "1");
        }else {
            setAttr("permissions", "2");
        }

        render("certIndex" + SystemConst.VIEW_EXTENDSION);
    }


    /**
     * 证书使用明细查询展示列表
     */
    public void certUseDetailListSearch() {
        int page = getParaToInt(SystemConst.DATATABLE_PAGINATE_OFFSET, SystemConst.DATATABLE_PAGINATE_OFFSET_DEFAULT);
        int rows = getParaToInt(SystemConst.DATATABLE_PAGINATE_LIMIT, SystemConst.DATATABLE_PAGINATE_LIMIT_DEFAULT);

        String sort = getPara(SystemConst.DATATABLE_PAGINATE_SORT, SystemConst.DEFAULT_ORDERBY_CREATETS);
        String order = getPara(SystemConst.DATATABLE_PAGINATE_ORDER, SystemConst.DATATABLE_PAGINATE_ORDER_DEFAULT);

        Authenticators authenticators = getModel(Authenticators.class);

        // 设备类型
        authenticators.put(ConditionConst.CONDITION_DEVICE_TYPE, getPara(ConditionConst.CONDITION_DEVICE_TYPE,null));
        // 设备名称
        authenticators.put(ConditionConst.CONDITION_DEVICE_NAME, getPara(ConditionConst.CONDITION_DEVICE_NAME,null));
        // 系统类型
        authenticators.put(ConditionConst.CONDITION_OS_TYPE, getPara(ConditionConst.CONDITION_OS_TYPE,null));
        // 系统版本
        authenticators.put(ConditionConst.CONDITION_OS_VERSION, getPara(ConditionConst.CONDITION_OS_VERSION,null));
        // 开始时间
        authenticators.put(ConditionConst.CONDITION_START_TIME, getPara(ConditionConst.CONDITION_START_TIME,null));
        // 结束时间
        authenticators.put(ConditionConst.CONDITION_END_TIME, getPara(ConditionConst.CONDITION_END_TIME,null));
        // 手机盾类型
        authenticators.put(ConditionConst.CONDITION_SECURE_LEVEL, getPara(ConditionConst.CONDITION_SECURE_LEVEL,null));
        // 用户名
        authenticators.put(ConditionConst.CONDITION_CUST_NO, getPara(ConditionConst.CONDITION_CUST_NO,null));

        Page<Authenticators> pages = new Page<Authenticators>();
        // 从缓存中取出"当前"用户信息
        User cacheUser = UAPSSOHelper.getUserByUapSessionId(getRequest());
        // 判断当前用户是否有权限
        boolean permissions = isTherePermissions();
        if (!permissions){
            if (StringUtils.isNotBlank(cacheUser.getInstCode())){
                // 当前用户所属的 机构号
                authenticators.put(ConditionConst.CONDITION_INST_CODE, cacheUser.getInstCode());
                pages = AuthenticatorsService.me.findCertUseDetaulList(authenticators, page, rows, sort, order);
            }
        }else {
            // 前台输入的 机构号
            authenticators.put(ConditionConst.CONDITION_INST_CODE, getPara(ConditionConst.CONDITION_INST_CODE,null));
            pages = AuthenticatorsService.me.findCertUseDetaulList(authenticators, page, rows, sort, order);
        }

        result.put(SystemConst.DATATABLE_PAGINATE_TOTAL, pages.getTotalRow());
        result.put(SystemConst.DATATABLE_PAGINATE_ROWS, pages.getList());

        render(responseJsonRender(result));
    }


    /**
     * 证书使用明细查询 导出
     */
    public void certUseDetailListExport(){

        Authenticators authenticators = getModel(Authenticators.class);
        // 设备类型
        authenticators.put(ConditionConst.CONDITION_DEVICE_TYPE, getPara(ConditionConst.CONDITION_DEVICE_TYPE,null));
        // 设备名称
        authenticators.put(ConditionConst.CONDITION_DEVICE_NAME, getPara(ConditionConst.CONDITION_DEVICE_NAME,null));
        // 系统类型
        authenticators.put(ConditionConst.CONDITION_OS_TYPE, getPara(ConditionConst.CONDITION_OS_TYPE,null));
        // 系统版本
        authenticators.put(ConditionConst.CONDITION_OS_VERSION, getPara(ConditionConst.CONDITION_OS_VERSION,null));
        // 开始时间
        authenticators.put(ConditionConst.CONDITION_START_TIME, getPara(ConditionConst.CONDITION_START_TIME,null));
        // 结束时间
        authenticators.put(ConditionConst.CONDITION_END_TIME, getPara(ConditionConst.CONDITION_END_TIME,null));
        // 安全级别、手机盾类型
        authenticators.put(ConditionConst.CONDITION_SECURE_LEVEL, getPara(ConditionConst.CONDITION_SECURE_LEVEL,null));
        // 用户名
        authenticators.put(ConditionConst.CONDITION_CUST_NO, getPara(ConditionConst.CONDITION_CUST_NO,null));
        // 机构号
        authenticators.put(ConditionConst.CONDITION_INST_CODE, getPara(ConditionConst.CONDITION_INST_CODE,null));


        String exportFileName = null;
        // 查询需要导出的明细数量
        int exportCount = AuthenticatorsService.me.exportCertUseDetaulCount(authenticators);

        // 证书明细导出的最大数量
        int certDetailExportMaxNum = PropKit.use(SystemConst.SYSTEM_CONFIG_FILE).getInt("cert.detail.export.max.num");
        if (exportCount > certDetailExportMaxNum){
            flag = false;
            message = "本次明细导出数量过大，已经大于"+ certDetailExportMaxNum +"条；请缩短检索时间或去数据库中使用sql导出！";
        }else {
            if (exportCount == 0){
                flag = false;
                message = "导出失败，不存在证书使用明细！";
            }else {
                List<Authenticators> list = AuthenticatorsService.me.exportCertUseDetaulList(authenticators);
                message = "导出失败！";
                // 导出Excel
                exportFileName = ExcelUtil.exportCertUseDetailExcel(list);
                if (exportFileName != null){
                    flag = true;
                    message = "导出成功！是否进行下载？";
                }
            }
        }
        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);
        result.put("exportFileName", exportFileName);
        render(responseJsonRender(result));
    }


    /**
     * 下载 导出成功的Excel
     */
    public void exportExcelDownload(){
        String fileName = getPara("fileName");
        String filePath = PathKit.getWebRootPath() + File.separator + "exportExcelFile" + File.separator + fileName;
        LOG.debug("filepath: "+filePath);

        File file = new File(filePath);
        render(new TempFileRender(file));
    }





    public void uploadFileForm() {
        render("uploadFileForm" + SystemConst.VIEW_EXTENDSION);
    }


    public void uploadFile(){
        int uploadFileSize = PropKit.use("application.properties").getInt("upload.file.size");
        String filePath = Identities.uuid2();

        try {
            UploadFile uploadFile = getFile("uploadFiles", filePath, uploadFileSize * 1024 * 1024);
            String filename = uploadFile.getFileName();
            filePath = uploadFile.getUploadPath();

            File file = uploadFile.getFile();

            List<Map<String,String>> deviceList = new ArrayList<Map<String, String>>();

            BufferedReader bfr = null;
            StringBuilder sb = new StringBuilder();
            try {
                bfr = new BufferedReader(new FileReader(file));
                String len = null;
                int i = 0;
                while ((len=bfr.readLine())!=null){
                    i++;
                    String[] strArr = len.split(",");
                    if(strArr.length == 4){
                        if(Strings.isNotBlank(strArr[0]) && Strings.isNotBlank(strArr[1]) && Strings.isNotBlank(strArr[2]) && Strings.isNotBlank(strArr[3])){
                            Map<String,String> m = new HashMap<String,String>();
                            m.put("device_type",strArr[0].trim());
                            m.put("device_name",strArr[1].trim());
                            m.put("device_type_alias",strArr[2].trim());
                            m.put("device_name_alias",strArr[3].trim());
                            deviceList.add(m);
                        }else {
                            result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
                            result.put(SystemConst.RESPONSE_RESULT_MESSAGE, "第"+i+"行数据格式不正确");
                            render(responseJsonRender(result));
                            return;
                        }
                    }else {
                        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
                        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, "第"+i+"行数据格式不正确");
                        render(responseJsonRender(result));
                        return;
                    }
                }

                if(deviceList.size() > 0) {

                    Devices.dao.deleteDeviceAlias();
                    Devices.dao.saveDeviceAlias(deviceList);
                    message = "上传成功";
                }

            } catch (FileNotFoundException e) {
            } catch (IOException e) {
            } finally {
                if(bfr!=null)
                    try {
                        bfr.close();
                    } catch (IOException e) {
                    }
            }



            FileUtils.deleteDirectory(new File(filePath));

        } catch (ExceededSizeException exceededSizeException) {
            message = "上传文件大小超过系统限制" + String.valueOf(uploadFileSize) + "M";
            LOG.error(message, exceededSizeException);
        } catch (IOException ioException) {
            LOG.error("删除目录出现异常", ioException);
        } catch (JSONException jsonException) {
            message = "数据内容解析现异常，请检查文件是否正确";
            LOG.error(message, jsonException);
        } catch (RuntimeException runtimeException) {
            message = "数据解析现异常，请检查文件是否正确";
            LOG.error(message, runtimeException);
        }

        //增加系统操作日志
        OperLogService.me.addOperLog("上传设备别名数据", message, flag, message, getRequest());

        result.put(SystemConst.RESPONSE_RESULT_FLAG, flag);
        result.put(SystemConst.RESPONSE_RESULT_MESSAGE, message);

        render(responseJsonRender(result));
    }

}
